package activity

import (
	"encoding/json"
	"longmen/server/config/global"
	"longmen/server/internal/services/consumers/publisher"
	"longmen/server/pkg/common/helper/const"
	"longmen/server/pkg/common/lib/rabbitmq"
	"longmen/server/pkg/db/mysql/db_main"
	"longmen/server/pkg/db/mysql/models/models_main"
	"strings"
	"sync"
	"time"

	"go.uber.org/zap"
	"longmen/server/pkg/common/api_models"
	"longmen/server/pkg/db/redis/cache"
)

type Activity struct {
	logger *zap.SugaredLogger
}

var instance *Activity
var once sync.Once
var funcMaps map[publisher.ActivityType]rabbitmq.Process

func New(log *zap.SugaredLogger) *Activity {
	once.Do(func() {
		instance = &Activity{
			logger: log,
		}
		funcMaps = map[publisher.ActivityType]rabbitmq.Process{
			publisher.Activity:       instance.activityEventHandler,
			publisher.Task:           instance.taskEventHandler,
			publisher.LiveWatchStats: instance.StatUserLiveWatchHandler,
		}
	})
	return instance
}

func (a *Activity) Process(data []byte) bool {
	resp := publisher.ActivityMessage{}
	err := json.Unmarshal(data, &resp)
	if err != nil {
		a.logger.Errorf("process msg error: %v", err)
		return false
	}
	process, ok := funcMaps[resp.ActType]
	if !ok {
		a.logger.Errorf("process not exists error: %d", resp.ActType)
		return false
	}

	return process(resp.Msg)
}

// 任务相关
func (a *Activity) taskEventHandler(msg []byte) bool {
	oUserTask := &models_main.UserTask{}
	oUserTaskTmp := &models_main.UserTask{}
	err := json.Unmarshal(msg, oUserTask)
	if err != nil { //完球了没有值
		global.Log.Warnf("userTask对象出错%s|%s", string(msg), err.Error())
		return true
	}
	a.logger.Debugf("收到订阅事件:%+v", string(msg))
	oUserTaskTmp, err = cache.GetUserTask(int(oUserTask.TaskId), int(oUserTask.Uid), true) //在这里取最新的值
	if err == nil {                                                                        //如果没有存进redis
		oUserTask = oUserTaskTmp
	}
	if sToken, err := cache.GetUserTokenLua(int(oUserTask.Uid)); err != nil || strings.EqualFold(sToken, ",") {
		global.Log.Warnf("用户不合法%v", oUserTask)
		return true
	}

	_, errLock := cache.GetUserTask(0, int(oUserTask.Uid), false)
	if errLock == nil { //有值，表示这个用户有一个任务正在处理
		time.Sleep(time.Second * 1)
		global.Log.Debugf("用户%d有并行任务", oUserTask.Uid)
		return false //重新入队
	}
	if oUserTask.IsReceived > 0 {
		global.Log.Debugf("已领取")
		return true
	}
	defer cache.DelUserTask(0, int(oUserTask.Uid))                      //删掉标记
	cache.SetUserTask(oUserTask, 0, int(oUserTask.Uid), time.Second*30) //标记：用户正有task在处理
	err = processTaskEvent(oUserTask)
	cache.DelUserTask(0, int(oUserTask.Uid)) //删掉标记
	if err != nil {
		global.Log.Error(err)
		//return false //重新推入
	}
	return true
}

// activityEventHandler 活动相关
func (a *Activity) activityEventHandler(msg []byte) bool {
	var finishedActivity *api_models.PubFinishedActivity
	err := json.Unmarshal(msg, &finishedActivity)
	if err != nil {
		a.logger.Errorf("err :%v", err)
		return false
	}
	a.logger.Debugf("收到订阅事件:%+v", finishedActivity)
	switch finishedActivity.Category {
	case _const.RegActivityType:
		err := db_main.RegActivity(finishedActivity.Uid)
		if err != nil {
			global.Log.Errorf("RegActivity err:%v", err)
			return false
		}
		cache.DelUserFullCache(finishedActivity.Uid)
	}
	return true
}

// StatUserRoomWatchHandler 直播间观看时长
func (s *Activity) StatUserLiveWatchHandler(msg []byte) bool {
	start := time.Now()
	defer func() {
		elapsed := time.Since(start)
		s.logger.Infof("StatUserLiveWatchHandler 执行耗时：%v", time.Since(start))
		if elapsed > 500*time.Millisecond {
			s.logger.Warnf("StatUserLiveWatchHandler 执行耗时过长：%v", elapsed)
		}
	}()
	var user struct {
		RoomId int
		models_main.User
	}
	err := json.Unmarshal(msg, &user)
	if err != nil {
		s.logger.Errorf("StatUserLiveWatchHandler err:%v", err)
		return false
	}

	//判断用户是否处于直播间页面
	structData, err := cache.GetLiveRoomUserInOutStatistics(user.RoomId, user.Id)
	if err != nil {
		return true
	}
	if structData.OutDeal {
		//用户已经退出直播间页面, 不计算时间
		return true
	}

	nowSec := time.Now().Unix()
	key := _const.LiveWatchDevice
	wd := cache.LiveWatchDevice{
		DeviceId: user.DeviceInfo,
		Duration: 0,
	}

	wds := global.GetRds().HGet(key, user.DeviceInfo).Val()
	if wds == "" {
		//记录最初观看时间到观众列表
		wd.StTime = nowSec
		wd.LastInstant = nowSec
		wd.Instant = nowSec
	} else {
		wd = *wd.Unmarshal(wds)
		if wd.IsOffline(nowSec) {
			//离线超过1分钟, 重新计算
			wd.StTime = nowSec
			wd.LastInstant = nowSec
			wd.Instant = nowSec
		} else {
			//记录最新的观看时间到观看时刻表
			wd.LastInstant = wd.Instant
			wd.Instant = nowSec
		}
	}
	wd.Duration += int(wd.Instant - wd.LastInstant)
	err = global.GetRds().HSet(key, user.DeviceInfo, wd.Marshal()).Err()
	if err != nil {
		s.logger.Debug("StatUserLiveWatchHandler Error: ", err)
		return false
	}

	if nowSec-wd.StTime > 0 {
		//需要更新的数据记录起来
		global.GetRds().HSet(_const.LiveWatchUpdateList, user.DeviceInfo, wd.Marshal())
	}
	return true
}
